#include "sqlconnpool.h"
using namespace std;

SqlConnPool::SqlConnPool() {
    useCount_ = 0; 
    freeCount_ = 0;
}

// 单例模式，懒汉方式
SqlConnPool* SqlConnPool::Instance() {
    static SqlConnPool connPool;
    return &connPool;
}

void SqlConnPool::Init(const char* host, int port, const char* user,
            const char* pwd, const char* dbName, int connSize = 10) {
    assert(connSize > 0);
    for(int i = 0; i < connSize; i++) {     // 创造SQL连接
        MYSQL* sql = nullptr;
        sql = mysql_init(sql);              //初始化
        if(!sql) {
            LOG_ERROR("MySql init error!"); //写日志
            assert(sql);
        }
        sql = mysql_real_connect(sql, host, user, pwd, dbName,
                                    port, nullptr, 0);
        if(!sql) {
            LOG_ERROR("MySql Connect error!");
        }
        connQue_.push(sql);     // 让该sql连接进入队列
    }
    MAX_CONN_ = connSize;
    sem_init(&semId_, 0, MAX_CONN_);    // 初始化为10
}

MYSQL* SqlConnPool::GetConn() {
    MYSQL* sql = nullptr;
    if(connQue_.empty()) {      // 没有连接建立
        LOG_WARN("SqlCoonPool busy!"); 
        return nullptr;
    }
    sem_wait(&semId_);              // 阻塞等待连接数量大于零
    lock_guard<mutex> locker(mtx_); // 锁定
    sql = connQue_.front();         // 得到队头连接
    connQue_.pop();                 // 清除连接
    return sql;
}

void SqlConnPool::FreeConn(MYSQL* sql) {
    assert(sql);
    lock_guard<mutex> locker(mtx_);
    connQue_.push(sql);     // 将使用完的连接加入队列
    sem_post(&semId_);      // 可用连接+1
}

void SqlConnPool::ClosePool() {
    lock_guard<mutex> locker(mtx_);
    while(!connQue_.empty()) {
        auto item = connQue_.front();
        connQue_.pop();
        mysql_close(item);
    }
    mysql_library_end();
}

int SqlConnPool::GetFreeConnCount() {
    lock_guard<mutex> locker(mtx_);
    return connQue_.size();
}

SqlConnPool::~SqlConnPool() {
    ClosePool();
}